﻿using RemoteSensingImageDirectServer.Models.Request.Params.OGC.RasterMap;
using RemoteSensingImageDirectServer.Models.Request.Response;
using RemoteSensingImageDirectServer.Register.Http;
using RemoteSensingImageDirectServer.Service.LRU;
using RemoteSensingImageDirectServer.Service.OGC.Metadata;
using RemoteSensingImageDirectServer.Service.OGC.RasterMap;
using RemoteSensingImageDirectServer.Untils.Extensions;
using RemoteSensingImageDirectServer.Untils.LRU;
using RemoteSensingImageDirectServer.Untils.Pool;
using RemoteSensingImageDirectServer.Untils.ScopeSpace;
using System.Text;

namespace RemoteSensingImageDirectServer.Service.Common
{
    public class RasterMapService : IRasterMapService
    {

        /// <summary>
        /// 参数校验
        /// </summary>
        private readonly IParamFormatService _formatService;

        /// <summary>
        /// 栅格数据服务元数据服务
        /// </summary>
        private readonly IRasterMapMetadata _rasterMapMetadata;

        /// <summary>
        /// 单景影像服务
        /// </summary>
        private readonly ISingleRasterMap _singleRasterMap;

        /// <summary>
        /// 单景影像高级服务
        /// </summary>
        private readonly ISingleAdRasterMap _singleAdRasterMap;

        /// <summary>
        /// 联合图层服务
        /// </summary>
        private readonly IGroupRasterMap _groupRasterMap;


        /// <summary>
        /// 影像缓存链表
        /// </summary>
        private readonly IRasterMapLink _mapLink;

        /// <summary>
        /// IP代理服务
        /// </summary>
        private readonly IInternetProxy _internetProxy;

        public RasterMapService(IParamFormatService formatService, IRasterMapMetadata rasterMapMetadata,
            ISingleRasterMap singleRasterMap, ISingleAdRasterMap singleAdRasterMap,
            IGroupRasterMap groupRasterMap,
            IRasterMapLink mapLink,
            IInternetProxy internetProxy)
        {
            this._formatService = formatService;
            this._rasterMapMetadata = rasterMapMetadata;
            this._singleRasterMap = singleRasterMap;
            this._singleAdRasterMap = singleAdRasterMap;
            this._groupRasterMap = groupRasterMap;
            this._mapLink = mapLink;
            this._internetProxy = internetProxy;
        }

        public ServiceResult GetData(SingleWMTSParams tileParam)
        {
            ServiceResult serviceResult = _formatService.Check(tileParam);
            if (serviceResult.Code == -1) return serviceResult;

            var singlePath = _formatService.GetSinglePath(tileParam.Layer, tileParam);
            var epsgCode = OsrTransformPool.Instance().GetEPSGFromSrs(tileParam.TileMatrixset);
            var key = (tileParam.Layer + epsgCode).ToMD5String();

            IRasterMapNode? rasterMapNode = _mapLink.Get(key);
            if (rasterMapNode == null)
            {
                rasterMapNode = _mapLink.Put(key, singlePath, tileParam.Maskfile, epsgCode);
            }

            if (tileParam.Request.ToLower() == "getcapabilities")
            {
                serviceResult = _rasterMapMetadata.GetCapabilities(rasterMapNode.GetMapSource(), tileParam,
                    _internetProxy.GetCurrentUri(), _internetProxy.GetCurrentUri());
            }
            else
            {
                serviceResult = _singleRasterMap.GetTile(rasterMapNode.GetMapSource(), tileParam);
            }

            return serviceResult;
        }

        public ServiceResult GetData(GroupWMTSParams tileParam)
        {
            ServiceResult serviceResult = _formatService.Check(tileParam);
            if (serviceResult.Code == -1) return serviceResult;

            var key = tileParam.Layer;

            IRasterMapNode? rasterMapNode = _mapLink.Get(key);
            if (rasterMapNode == null)
            {
                rasterMapNode = _mapLink.Put(key);
            }


            if (tileParam.Request.ToLower() == "getcapabilities")
            {
                serviceResult = _rasterMapMetadata.GetCapabilities(rasterMapNode.GetMapSource(), tileParam,
                    _internetProxy.GetCurrentUri(), _internetProxy.GetCurrentUri());
            }
            else
            {
                serviceResult = _groupRasterMap.GetTile(rasterMapNode.GetMapSource(), tileParam);
            }
            return serviceResult;
        }

        public ServiceResult GetData(SingleAdWMTSParams tileParam)
        {
            ServiceResult serviceResult = _formatService.Check(tileParam);
            if (serviceResult.Code == -1) return serviceResult;
            throw new NotImplementedException();
        }

        public ServiceResult GetData(SingleWMSParams tileParam)
        {
            ServiceResult serviceResult = _formatService.Check(tileParam);
            if (serviceResult.Code == -1) return serviceResult;

            var singlePath = _formatService.GetSinglePath(tileParam.Layers, tileParam);
            var coordinateSystem = tileParam.Crs ?? tileParam.Srs;
            var epsgCode = OsrTransformPool.Instance().GetEPSGFromSrs(coordinateSystem);
            var key = (tileParam.Layers + epsgCode).ToMD5String();
            IRasterMapNode? rasterMapNode = _mapLink.Get(key);
            if (rasterMapNode == null)
            {
                rasterMapNode = _mapLink.Put(key, singlePath, tileParam.Maskfile, epsgCode);
            }

            if (tileParam.Request.ToLower() == "getcapabilities")
            {
                serviceResult = _rasterMapMetadata.GetCapabilities(rasterMapNode.GetMapSource(), tileParam,
                    _internetProxy.GetCurrentUri(), _internetProxy.GetCurrentUri());
            }
            else
            {
                serviceResult = _singleRasterMap.GetTile(rasterMapNode.GetMapSource(), tileParam);
            }

            return serviceResult;
        }

        public ServiceResult GetData(GroupWMSParams tileParam)
        {
            ServiceResult serviceResult = _formatService.Check(tileParam);
            if (serviceResult.Code == -1) return serviceResult;

            var key = tileParam.Layers;

            IRasterMapNode? rasterMapNode = _mapLink.Get(key);
            if (rasterMapNode == null)
            {
                rasterMapNode = _mapLink.Put(key);
            }

            if (tileParam.Request.ToLower() == "getcapabilities")
            {
                serviceResult = _rasterMapMetadata.GetCapabilities(rasterMapNode.GetMapSource(), tileParam,
                    _internetProxy.GetCurrentUri(), _internetProxy.GetCurrentUri());
            }
            else
            {
                serviceResult = _groupRasterMap.GetTile(rasterMapNode.GetMapSource(), tileParam);
            }
            return serviceResult;
        }

        public ServiceResult GetData(SingleAdWMSParams tileParam)
        {
            ServiceResult serviceResult = _formatService.Check(tileParam);
            if (serviceResult.Code == -1) return serviceResult;
            throw new NotImplementedException();
        }
    }
}
